package cn.chiship.framework.common.service.impl;

import cn.chiship.framework.common.constants.SystemConfigConstants;
import cn.chiship.framework.common.pojo.vo.ConfigJson;
import cn.chiship.framework.common.pojo.vo.SystemConfigVo;
import cn.chiship.framework.common.pojo.vo.ThirdApplicationKeyConfigVo;
import cn.chiship.framework.common.util.FrameworkUtil2;
import cn.chiship.sdk.core.base.BaseResult;
import cn.chiship.sdk.core.base.constants.BaseCacheConstants;
import cn.chiship.sdk.core.base.constants.BaseConstants;
import cn.chiship.sdk.core.encryption.rsa.RsaEncrypt;
import cn.chiship.sdk.core.exception.custom.BusinessException;
import cn.chiship.sdk.core.util.Base64Util;
import cn.chiship.sdk.core.util.PrintUtil;
import cn.chiship.sdk.core.util.StringUtil;
import cn.chiship.sdk.third.core.model.WeiXinConfigModel;
import com.alibaba.fastjson.JSONObject;
import cn.chiship.sdk.cache.service.RedisService;
import cn.chiship.framework.common.constants.CommonCacheConstants;
import cn.chiship.framework.common.pojo.vo.EmailSettingVo;
import cn.chiship.framework.common.service.GlobalCacheService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

/**
 * 全局缓存服务实现
 *
 * @author lijian
 */
@Service
public class GlobalCacheServiceImpl implements GlobalCacheService {

    private static final String ZERO_IP = "0.0.0.0";

    @Resource
    RedisService redisService;

    @Override
    public BaseResult validateLoginIp(String ip) {
        ConfigJson configJson = getSystemConfigJson(
                Arrays.asList(SystemConfigConstants.IS_SYSTEM_IP, SystemConfigConstants.SYSTEM_IP_WHITELIST));
        if (StringUtil.isNull(configJson)) {
            return BaseResult.ok();
        }
        if (String.valueOf(BaseConstants.YES).equals(configJson.getString(SystemConfigConstants.IS_SYSTEM_IP))) {
            String whiteIp = configJson.getString(SystemConfigConstants.SYSTEM_IP_WHITELIST);
            if (StringUtil.isNullOrEmpty(whiteIp)) {
                return BaseResult.error("系统启动IP限制，但还未配置!");
            }
            if (whiteIp.indexOf(ZERO_IP) > -1) {
                return BaseResult.ok();
            }
            if (whiteIp.indexOf(ip) > -1) {
                return BaseResult.ok();
            }
            return BaseResult.error("系统禁止IP[" + ip + "]访问,联系管理员添加IP至白名单");
        }
        return BaseResult.ok();

    }

    @Override
    public EmailSettingVo getEmailSettingConfig() {
        EmailSettingVo emailSettingVo = (EmailSettingVo) redisService
                .get(CommonCacheConstants.buildKey(BaseCacheConstants.REDIS_EMAIL_SETTING_PREFIX));
        if (null == emailSettingVo) {
            return null;
        }
        return emailSettingVo;
    }

    @Override
    public String getRsaPrivateKey() {
        JSONObject prof = (JSONObject) redisService
                .get(CommonCacheConstants.buildKey(BaseCacheConstants.REDIS_PROOF_PREFIX));
        return prof.getString("privateKey");
    }

    @Override
    public String getRsaPublicKey() {
        JSONObject prof = (JSONObject) redisService
                .get(CommonCacheConstants.buildKey(BaseCacheConstants.REDIS_PROOF_PREFIX));
        return prof.getString("publicKey");
    }

    @Override
    public SystemConfigVo getSystemConfig(String key) {
        List<SystemConfigVo> systemConfigVos = getSystemConfig(Arrays.asList(key));
        if (!systemConfigVos.isEmpty()) {
            return systemConfigVos.get(0);
        }
        return null;
    }

    @Override
    public List<SystemConfigVo> getSystemConfig(List<String> keys) {
        List<SystemConfigVo> configVos = new ArrayList<>();
        for (String key : keys) {
            SystemConfigVo systemConfigVo = (SystemConfigVo) redisService
                    .hget(CommonCacheConstants.buildKey(BaseCacheConstants.REDIS_SYSTEM_CONFIG_PREFIX), key);
            if (!StringUtil.isNull(systemConfigVo)) {
                configVos.add(systemConfigVo);
            }
        }
        return configVos;
    }

    @Override
    public ConfigJson getSystemConfigJson(List<String> keys) {
        ConfigJson json = new ConfigJson();
        List<SystemConfigVo> systemConfigVos = getSystemConfig(keys);
        for (SystemConfigVo configVo : systemConfigVos) {
            json.put(configVo.getParamCode(), configVo.getParamValue());
        }
        return json;
    }

    @Override
    public ConfigJson getSystemConfigJson(String key) {
        return getSystemConfigJson(Arrays.asList(key));
    }

    @Override
    public String rsaDecrypt(String value, String title) {
        try {
            return new String(
                    RsaEncrypt.decrypt(RsaEncrypt.loadPrivateKeyByStr(getRsaPrivateKey()), Base64Util.decode(value)));
        } catch (Exception e) {
            throw new BusinessException(title + e.getLocalizedMessage());
        }
    }

    @Override
    public BaseResult verificationSmsCode(String codeDevice, String code) {
        String key = String.format("%s:*:%s-%s",
                CommonCacheConstants.buildKey(CommonCacheConstants.REDIS_SMS_CODE_PREFIX), codeDevice, code);
        Set<String> keys = redisService.keys(key);
        if (keys.isEmpty()) {
            return BaseResult.error("验证码错误,请重新输入!");
        }
        key = keys.iterator().next();
        Map<String, Object> map = (Map<String, Object>) redisService.get(key);
        Long expireTime = (Long) map.get("expireTime");
        Byte isUsed = (Byte) map.get("isUsed");
        if (System.currentTimeMillis() > expireTime) {
            return BaseResult.error("验证码已失效,请重新发送!");
        }
        if (BaseConstants.YES == isUsed) {
            return BaseResult.error("验证码已使用,请重新发送!");
        }
        map.put("isUsed", BaseConstants.YES);
        Integer duration = (Integer) map.get("duration");
        redisService.del(key);
        redisService.set(String.format("%s:1:%s-%s",
                        CommonCacheConstants.buildKey(CommonCacheConstants.REDIS_SMS_CODE_PREFIX), codeDevice, code), map,
                duration);
        return BaseResult.ok();
    }


    @Override
    public ThirdApplicationKeyConfigVo getThirdApplicationConfigByAppId(String appId) {
        String key = CommonCacheConstants.buildKey(BaseCacheConstants.REDIS_THIRD_CONFIG_PREFIX);
        if (!redisService.hHasKey(key, FrameworkUtil2.getChishipDefaultProperties().getId() + "-" + appId)) {
            throw new BusinessException("不存在的三方应用【" + appId + "】");
        }
        return (ThirdApplicationKeyConfigVo) redisService.hget(key, FrameworkUtil2.getChishipDefaultProperties().getId() + "-" + appId);

    }

    @Override
    public WeiXinConfigModel getWeiXinConfigByAppId(String appId) {
        if (StringUtil.isNullOrEmpty(appId)) {
            return null;
        }
        ThirdApplicationKeyConfigVo applicationKeyConfig = getThirdApplicationConfigByAppId(appId);
        return new WeiXinConfigModel(
                applicationKeyConfig.getAppId(),
                applicationKeyConfig.getAppSecret()
        );
    }
}
